package com.example.design_pattern.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理：
public class ProxyTest03 {
    public static void main(String[] args) {

        // 创建被代理对象1，金莲对象
        JinLian jl = new JinLian();
        // 创建被代理对象2，阎婆惜对象
        YanPoXi ypx = new YanPoXi();

        // 获得被代理对象的相关信息
        // 获得被代理对象的类加载器
        ClassLoader classLoader1 = JinLian.class.getClassLoader();
        ClassLoader classLoader2 = YanPoXi.class.getClassLoader();
        // 获得被代理对象实现的所有接口
        Class<?>[] interfaces1 = JinLian.class.getInterfaces();
        Class<?>[] interfaces2 = YanPoXi.class.getInterfaces();

        // 动态生成一个金莲类的代理对象，这个FindHappy proxy就相当于以前的WangPo wp1。
        // 生成的代理对象所属的类不知道是什么类型,但该类一定实现了与被代理类相同的接口，所以，我们就可以直接转型到接口的类型(FindHappy)。
        FindHappy proxy1 = (FindHappy) Proxy.newProxyInstance(
                classLoader1,
                interfaces1,
                // 匿名内部类的写法
                // 整个new InvocationHandler(){}的本质就是InvocationHandler接口的一个实现类的一个实例对象。InvocationHandler是接口名。{}就是实现类里面实现的代码。
                // 只要后续代理对象调用方法,就会调用到new InvocationHandler(){} 里面的ivoke方法
                new InvocationHandler() {
                    // Object proxy，参数1: 表示生成的代理对象,慎用
                    // Method method，参数2: 表示代理对象调用的方法
                    // Object[] args，参数3: 表示代理对象调用的方法的实际参数
                    // Object，返回值: 其实就是代理对象调用的方法的返回值
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 被代理者调用自己要调用的方法
                        // jl.happy(); //这是以前的写法。现在我们用反射来调用。
                        method.invoke(jl, args);
                        return null;
                    }
                }
        );

        FindHappy proxy2 = (FindHappy) Proxy.newProxyInstance(
                classLoader2,
                interfaces2,
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // ypx.happy();
                        method.invoke(ypx, args);
                        return null;
                    }
                }
        );

        // 代理对象调用happy方法
        proxy1.happy();
        proxy2.happy();

    }
}




